home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / tpa2_a.arc / FIND.PAS < prev    next >
Pascal/Delphi Source File  |  1991-04-28  |  7KB  |  173 lines

  1. {═════════════════════════════ FIND.PAS ═════════════════════════════}
  2. { Usage:  Find                 (From Editor, just Run)               }
  3. {═════════════════════════════ FIND.PAS ═════════════════════════════}
  4.  
  5. {- This demonstration illustrates the advantage of using assembly    }
  6. {- language to improve execution speed of time consuming operations. }
  7. {- Searches about 30,000 bytes of memory for the string FindString   }
  8. {- and repeats 10 times.  On my 8MHz 8086 based machine this takes   }
  9. {- 0.7 seconds in assembly language and about 10 times that long in  }
  10. {- Pascal.  You can dramatically improve operations on large text    }
  11. {- files by using BlockRead (into a Buffer), Find(BufPtr,256,CrLf)   }
  12. {- (to find line ends), and Move (into a standard String variable)   }
  13. {- in place of repeated calls to ReadLn.                             }
  14.  
  15.  
  16. {═══════════════════════════════ Find ═══════════════════════════════}
  17. { Search memory (case sensitive) for string FindStr.  Return number  }
  18. { of characters skipped to find a match, or SearchLimit if no match  }
  19. { Checks entire FindStr even if end of FindStr is beyond SearchLimit }
  20. { Thus: Find(StartAddr,1,FindStr)=0 only if FindStr is at StartAddr  }
  21. {═══════════════════════════════ Find ═══════════════════════════════}
  22. TYPE St63= String[63];
  23. FUNCTION Find( VAR StartAddr; SearchLimit:INTEGER; FindStr:St63 ): INTEGER;
  24. BEGIN
  25. ASSEMBLE
  26. ;- NOTE that the [Bp] specification required to reference parameters
  27. ;-  and local variables is supplied automatically by TP&Asm.
  28. ;-  You may code the [Bp]'s explicitly if you prefer ( StartAddr[Bp] ),
  29. ;-  and you may disable presumptions for "WYSIWYG" assembly.
  30. ;- Remember - TP&Asm knows how to find all your Pascal variables because
  31. ;-  it assembles during the compile step!
  32.  
  33.    Cld                ; Set forward direction for Lodsb/w and Cmpsb
  34.    Mov Cx,SearchLimit ; Maximum bytes to search
  35.    Mov Dx,Cx          ; Save in Dx
  36.    Les Di,StartAddr   ; point Es:[Di] to StartAddr
  37.  
  38.    Lea Si,FindStr     ; NOTE: String Value is located in Stack Segment
  39.    Lodsw              ; Al <-- Ss:[Si], Ah <-- Ss:[Si+1], Si <-- Si+2
  40.  
  41. ;- Lodsw normally loads from Ds:[Si], however TP&Asm correctly presumes
  42. ;-  and supplies the Ss override necessary to obtain access to FindStr.
  43. ;-  You may code the override explicitly if you prefer ( Ss LodsW ),
  44. ;-  and you may disable presumptions for "WYSIWYG" assembly.
  45.  
  46.    Xchg Ah,Al         ; Now FindStrLen is in Ah, FindStr[1] is in Al
  47.  
  48. ScanLoop:
  49.    RepNE Scasb        ; Fast Scan Es:[Di] for Al; Di <-- [match]+1
  50.    jNE Finish         ; If no match found, return SearchLimit saved in Dx
  51.    Push Cx,Di         ; Save Cx & Di in case this 'Find' is premature
  52.    Xor Ch,Ch          ; Clear Ch
  53.    Mov Cl,Ah          ; Load FindStrLen
  54.    Dec Cl             ; FindStr[1] has already been checked
  55. L1:
  56.    CmpsB              ; Compare Ss:[Si] =? Es:[Di], Inc Di, Inc Si
  57.    LoopE L1           ; Repeat while equal, Dec Cx
  58.    Pop Di,Cx          ; Restore Cx & Di, Find NEXT occurrance of Al
  59.    jNE ScanLoop       ; - Jmp only if exitted LoopE with NE (miscompare)
  60.    Inc Cx             ; Arrive here if string found
  61.    Sub Dx,Cx          ; Find number of bytes skipped
  62. Finish:
  63.    Mov Find,Dx        ; Put in function result
  64. END; {Assemble}
  65. END; {FUNCTION Find}
  66.  
  67.  
  68. {═════════════════════════════ PasFind ══════════════════════════════}
  69. { Same as FUNCTION Find but written in Pascal rather than Assembly   }
  70. {═════════════════════════════ PasFind ══════════════════════════════}
  71. FUNCTION PasFind(VAR StartAddr; SearchLimit:INTEGER; FindStr:St63):INTEGER;
  72. VAR m,n:INTEGER;
  73.   FindArray: ARRAY[0..$7FF0] OF CHAR Absolute StartAddr;
  74. BEGIN
  75.   m := 0;
  76.   FOR n := 0 TO SearchLimit DO BEGIN
  77.     IF FindArray[n] = FindStr[1] THEN BEGIN
  78.       WHILE FindArray[n+m]=FindStr[1+m] DO m:=m+1;
  79.       IF m >= Length(FindStr) THEN BEGIN
  80.         PasFind := n; Exit;
  81.       END; {IF m >= Length(FindStr) THEN }
  82.       m := 0;
  83.     END; {IF FindArray[n] = FindStr[1] THEN }
  84.   END; {FOR n := 0 TO SearchLimit DO }
  85.   PasFind := SearchLimit;
  86. END; {FUNCTION PasFind}
  87.  
  88.  
  89. {═════════════════════════════ GetTime ══════════════════════════════}
  90. { Compatible with Version 4 & 5 DOS Unit Procedure.                  }
  91. {═════════════════════════════ GetTime ══════════════════════════════}
  92. PROCEDURE GetTime( VAR Hour, Minute, Second, Hundredth: INTEGER);
  93. VAR HrMin, SecHn: INTEGER;
  94. BEGIN
  95.   Assemble
  96.     Mov Ah,2Ch
  97.     Int 21h        ; Get System time into Cx:Dx
  98.     Xor Ah,Ah
  99.     Mov Al,Ch      ; Now Ax = System hour
  100.  
  101.  ;- Use the parameter pointers to store VAR results in assembly language ..
  102.     Les Di,Hour    ; Es:[Di] points to Hour
  103.     Es Mov [Di],Ax ; Save Hour value in Es:[Di]
  104.  
  105.  ;- .. or save into local variables ..
  106.     Mov HrMin,Cx
  107.     Mov SecHn,Dx
  108.   End; {Assemble}
  109.  
  110.  {- .. and let the compiler do the work: -}
  111.   Minute := Lo(HrMin);
  112.   Second := Hi(SecHn);
  113.   Hundredth := Lo(SecHn);
  114. END; {PROCEDURE GetTime}
  115.  
  116.  
  117. {══════════════════ A couple of Display Functions ═══════════════════}
  118. TYPE Str2 = STRING[2];
  119. FUNCTION TwoDgt(N: INTEGER): Str2; VAR Tmp: Str2;
  120. BEGIN
  121.   Str(N:2,Tmp); IF N<10 THEN Tmp[1] := '0'; TwoDgt := Tmp;
  122. END; {FUNCTION TwoDgt}
  123.  
  124. TYPE Str12 = STRING[12];
  125. FUNCTION TimeDisplay: Str12;
  126. VAR  Hour, Minute, Second, Hundredth: INTEGER;
  127. BEGIN
  128.   GetTime( Hour, Minute, Second, Hundredth );
  129.   TimeDisplay := TwoDgt(Hour) +':' +TwoDgt(Minute) +':' +TwoDgt(Second)
  130.                +'.' +TwoDgt(Hundredth);
  131. END; {TimeDisplay}
  132. {══════════════════ A couple of Display Functions ═══════════════════}
  133.  
  134.  
  135. VAR
  136.   BigArray: ARRAY[1..30000] OF BYTE;
  137.   FindString: String[80];
  138.   FindLoc,n : INTEGER;
  139.  
  140. CONST
  141.   MaxSearch = 32000;
  142.   Repeats = 10;
  143.  
  144. BEGIN
  145.  
  146.   FillChar(BigArray,SizeOf(BigArray),' ');
  147.   FindString := 'Find This String';
  148.  
  149.   WRITELN('Asm Find Test:');
  150.   WRITELN('Start  search at ',TimeDisplay);
  151.  
  152.   FOR n := 1 TO Repeats DO FindLoc := Find(BigArray,MaxSearch,FindString);
  153.  
  154.   IF FindLoc = MaxSearch THEN WRITE('String NOT FOUND!')
  155.                          ELSE WRITE('Found at ',FindLoc);
  156.   WRITELN('   Should Find at: ', 1+ SizeOf(BigArray));
  157.   WRITELN('Finish search at ',TimeDisplay);
  158.   WRITELN;
  159.  
  160.  
  161.   WRITELN('Pas Find Test:');
  162.   WRITELN('Start  search at ',TimeDisplay);
  163.  
  164.   FOR n := 1 TO Repeats DO FindLoc := PasFind(BigArray,MaxSearch,FindString);
  165.  
  166.   IF FindLoc = MaxSearch THEN WRITE('String NOT FOUND!')
  167.                          ELSE WRITE('Found at ',FindLoc);
  168.   WRITELN('   Should Find at: ', 1+ SizeOf(BigArray));
  169.   WRITELN('Finish search at ',TimeDisplay);
  170.   WRITELN;
  171.  
  172. END.
  173.